#include <iostream>
#include <fstream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
#include<cstring>

using namespace std;


int CheckPath(char *path){
    // return 0 path is folder
    // return 1 path is file
    // return 2 path is not exist
    // return 3 error
    struct stat info;
    int r = stat(path, &info);
    if (r==0){
        if(S_ISDIR(info.st_mode))
            return 0; 
        else
            return 1;
    }
    else{
        if(errno==ENOENT)
            return 2;
        else
            return 3;
    }
}

string Getdirpath(char*path){
    char* src = path;
    string filename;
    int i = strlen(src) - 1;
    while(i>0)
    {
        if(src[i]=='/')
        {
            for(i=i+1;i<strlen(src);i++)
                filename += src[i];
            break;
        }
        i--;
    }
    if (filename.length() == 0)
        filename = src;
    return filename;
}

int Copy2dir(char* Source, char* Target){
    char *src = Source;
    char *trg = Target;

    ifstream fin(src);
    if (!fin){
        cout<<"[Error] Source file does not exsit\n";
        return 0;
    }

    ofstream fout(trg);
    if(!fout){
        string filename = Getdirpath(src);
        strcat(trg,"/");
        strcat(trg,filename.c_str());
        fout.open(trg);
    }
    string temp;
    while(getline(fin,temp))
        fout << temp;
    fin.close();
    fout.close();
}

int Copyfile(char* Source, char* Target){
    ifstream in;
    ofstream out;
    in.open(Source);

    if (access(Target, 0)==0){
        cout << "[Warnning] Target file exist. Please choose blow operation:\n[1] Overwrite target file\n[2] Merge with target file\n[3] Cancel\n";

        int select;
        cout << "[Info] Please input:\t";
        cin >> select;
        switch(select) {
            case 1:
                //overwrite target file
                out.open(Target);
                out<<in.rdbuf();
                break;
            case 2:
                //merge with target file
                out.open(Target, ios::app);
                out<<in.rdbuf();
                break;
            case 3:
                // cancel
                cout << "[Info] Cancel\n";
                return 0;
            default:
                cout<<"[Error] Please choose the right number\n";
        } 
    }
    else{
        out.open(Target);
        out<<in.rdbuf();
    }
    in.close();
    out.close();
    return 0;
}

int mycopy(char* Source, char* Target){
    int source_type = CheckPath(Source);
    switch (source_type){
        case 0:{
            cout << "[Error] Source file (" << Source << ")is a folder\n";
            return 0;
        }
        case 1:{
            cout << "[Info] Source file("<< Source << ") exists\n";
            int target_type = CheckPath(Target);
            switch (target_type){
            case 0:
                cout << "[Info] Target file("<< Target << ") is a folder\n";
                Copy2dir(Source, Target);
                return 0;
            case 1:
                cout << "[Error] Target file(" << Target << ") is a file\n";
                Copyfile(Source, Target);
                return 0;
            case 2:
                cout<< "[Error] Target file("<< Target << ") is not exsit\n";
                Copyfile(Source, Target);
                return 0;
            default:
                cout << "[Error]";
                return 0;
            }
        }
        case 2:{
            cout << "[Error] Source file("<< Source <<") does not exit\n";
            break; 
        }
        default:{
            cout << "[Error] Missing parameters\n";
        }
    }
}

int main(int argc, char* argv[]){
    mycopy(argv[1], argv[2]);

    return 0;
}